/// @tags: NetworkFlow ScanLine
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

namespace BlueQuantum {

typedef pair<int, int> PII;

int const N = 4e4 + 5, INF = 0x3f3f3f3f;

int n, q, e_cnt = 1, s, t, eve_cnt;
int n_cnt;
int heads[N], dep[N], cur[N];
int lef[N];

struct Edge {
  int v, nxt, f;
} e[10000000 + 5];

struct Node {
  int x1, x2, y;
  bool typ;
  inline bool operator<(Node const &rhs) const {
    return y != rhs.y ? y < rhs.y : typ < rhs.typ;
  }
} eve[N * 2];

inline void add(int u, int v, int f) {
  e[++e_cnt].v = v, e[e_cnt].nxt = heads[u], heads[u] = e_cnt, e[e_cnt].f = f;
  e[++e_cnt].v = u, e[e_cnt].nxt = heads[v], heads[v] = e_cnt, e[e_cnt].f = 0;
}

inline int id(int l, int r, int typ) { return typ * n_cnt + ((l + r) | (l != r)); }

void build(int l, int r, int typ) {
  int x = id(l, r, typ);
  if (l == r) {
    if (typ == 0) add(s, x, 1);
    if (typ == 1) add(x, t, 1);
    return;
  }
  int mid = (l + r) >> 1;
  build(l, mid, typ), build(mid + 1, r, typ);
  if (typ == 0)
    add(id(l, mid, typ), x, INF), add(id(mid + 1, r, typ), x, INF);
  else
    add(x, id(l, mid, typ), INF), add(x, id(mid + 1, r, typ), INF);
}

void modify(int l, int r, int typ, int L, int R, vector<PII> &vec) {
  if (L <= l && r <= R) return vec.push_back(make_pair(id(l, r, typ), r - l + 1));
  int mid = (l + r) >> 1;
  if (L <= mid) modify(l, mid, typ, L, R, vec);
  if (mid < R) modify(mid + 1, r, typ, L, R, vec);
}

inline void update(int l, int r, int L, int R) {
  static vector<PII> A, B;
  A.clear(), B.clear();
  modify(1, n, 0, l, r, A), modify(1, n, 1, L, R, B);
  for (vector<PII>::iterator i = A.begin(), ilim = A.end(); i != ilim; ++i)
    for (vector<PII>::iterator j = B.begin(), jlim = B.end(); j != jlim; ++j)
      add(i->first, j->first, i->second * j->second);
}

inline bool bfs() {
  memcpy(cur, heads, sizeof(cur));
  memset(dep, 0, sizeof(dep));
  queue<int> q;
  q.push(s);
  dep[s] = 1;
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = heads[u], v; i; i = e[i].nxt) {
      if (dep[v = e[i].v] == 0 && e[i].f) {
        dep[v] = dep[u] + 1;
        if (v == t) return true;
        q.push(v);
      }
    }
  }
  return false;
}

int dinic(int u, int flow) {
  if (u == t) return flow;
  int rest = flow, k;
  for (int &i = cur[u], v; i; i = e[i].nxt) {
    if (dep[v = e[i].v] == dep[u] + 1 && e[i].f) {
      k = dinic(v, min(rest, e[i].f));
      if (k == 0) dep[v] = 0;
      e[i].f -= k;
      e[i ^ 1].f += k;
      rest -= k;
      if (rest == 0) break;
    }
  }
  return flow - rest;
}

inline int getMaxFlow() {
  int res = 0;
  while (bfs()) res += dinic(s, INF);
  return res;
}

inline int main() {
  cin >> n >> q;
  for (int x1, y1, x2, y2; q; --q) {
    cin >> x1 >> y1 >> x2 >> y2;
    eve[++eve_cnt] = (Node){x1, x2, y1, false};
    eve[++eve_cnt] = (Node){x1, x2, y2, true};
  }
  eve[++eve_cnt] = (Node){1, n, n + 1, false}, eve[++eve_cnt] = (Node){1, n, n + 1, true};
  sort(eve + 1, eve + eve_cnt + 1);
  n_cnt = id(n, n, 0);
  s = n_cnt * 2 + 3, t = s + 1;
  build(1, n, 0), build(1, n, 1);
  for (int i = 1; i <= eve_cnt; ++i) {
    if (eve[i].typ == 1)
      for (int j = eve[i].x1; j <= eve[i].x2; ++j) lef[j] = eve[i].y;
    else {
      for (int j = eve[i].x1, lasw = eve[i].y - 1, lash = 0; j <= eve[i].x2 + 1; ++j) {
        if (j == eve[i].x2 + 1 || lef[j] ^ lasw) {
          if (lasw + 1 < eve[i].y) update(lash, j - 1, lasw + 1, eve[i].y - 1);
          lasw = lef[j], lash = j;
        }
      }
    }
  }
  cout << getMaxFlow();
  return 0;
}

}  // namespace BlueQuantum

int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
  freopen("/tmp/CodeTmp/testdata.in", "r", stdin);
  freopen("/tmp/CodeTmp/testdata.out", "w", stdout);
#else
  freopen("CF793G Oleg and chess.in", "r", stdin);
  freopen("CF793G Oleg and chess.out", "w", stdout);
#endif
#endif

  ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
  return BlueQuantum::main();
}
